From f1c6ac275100049f23080540262b3583bc546428 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 25 Oct 2006 14:48:55 -0600 Subject: [PATCH] [IA64] NUMA support Based on patch from Tristan Gingold Signed-off-by: Alex Williamson --- .../arch/ia64/xen/xcom_privcmd.c | 31 +++++++- xen/arch/ia64/linux-xen/Makefile | 2 + xen/arch/ia64/linux-xen/README.origin | 2 + xen/arch/ia64/linux-xen/mm_contig.c | 2 +- xen/arch/ia64/linux-xen/mm_numa.c | 75 ++++++++++++++++++ xen/arch/ia64/linux-xen/numa.c | 67 ++++++++++++++++ xen/arch/ia64/xen/acpi.c | 2 + xen/arch/ia64/xen/dom0_ops.c | 76 ++++++++++++++++++- xen/include/asm-ia64/config.h | 6 ++ xen/include/asm-ia64/linux-null/asm/mmzone.h | 1 + .../asm-ia64/linux-xen/asm/README.origin | 2 + .../asm-ia64/{linux => linux-xen}/asm/acpi.h | 2 + .../asm-ia64/{linux => linux-xen}/asm/numa.h | 6 ++ xen/include/asm-ia64/linux/asm/README.origin | 3 +- xen/include/asm-ia64/linux/asm/nodedata.h | 52 +++++++++++++ xen/include/asm-ia64/xenpage.h | 4 - xen/include/public/arch-ia64.h | 1 + 17 files changed, 322 insertions(+), 12 deletions(-) create mode 100644 xen/arch/ia64/linux-xen/mm_numa.c create mode 100644 xen/arch/ia64/linux-xen/numa.c create mode 100644 xen/include/asm-ia64/linux-null/asm/mmzone.h rename xen/include/asm-ia64/{linux => linux-xen}/asm/acpi.h (99%) rename xen/include/asm-ia64/{linux => linux-xen}/asm/numa.h (93%) create mode 100644 xen/include/asm-ia64/linux/asm/nodedata.h diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c index c11fe1ec05..7d50fffd51 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c @@ -78,6 +78,12 @@ xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall) return ret; } +/* + * Temporarily disable the NUMA PHYSINFO code until the rest of the + * changes are upstream. + */ +#undef IA64_NUMA_PHYSINFO + static int xencomm_privcmd_sysctl(privcmd_hypercall_t *hypercall) { @@ -108,7 +114,9 @@ xencomm_privcmd_sysctl(privcmd_hypercall_t *hypercall) (void *)desc); break; case XEN_SYSCTL_tbuf_op: +#ifndef IA64_NUMA_PHYSINFO case XEN_SYSCTL_physinfo: +#endif case XEN_SYSCTL_sched_id: break; case XEN_SYSCTL_perfc_op: @@ -140,6 +148,27 @@ xencomm_privcmd_sysctl(privcmd_hypercall_t *hypercall) set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer, (void *)desc); break; +#ifdef IA64_NUMA_PHYSINFO + case XEN_SYSCTL_physinfo: + ret = xencomm_create( + xen_guest_handle(kern_op.u.physinfo.memory_chunks), + PUBLIC_MAXCHUNKS * sizeof(node_data_t), + &desc, GFP_KERNEL); + if (ret) + return ret; + set_xen_guest_handle(kern_op.u.physinfo.memory_chunks, + (void *)desc); + + ret = xencomm_create( + xen_guest_handle(kern_op.u.physinfo.cpu_to_node), + PUBLIC_MAX_NUMNODES * sizeof(u64), + &desc1, GFP_KERNEL); + if (ret) + xencomm_free(desc); + set_xen_guest_handle(kern_op.u.physinfo.cpu_to_node, + (void *)desc1); + break; +#endif default: printk("%s: unknown sysctl cmd %d\n", __func__, kern_op.cmd); return -ENOSYS; @@ -152,7 +181,7 @@ xencomm_privcmd_sysctl(privcmd_hypercall_t *hypercall) ret = xencomm_arch_hypercall_sysctl(op_desc); - /* FIXME: should we restore the handle? */ + /* FIXME: should we restore the handles? */ if (copy_to_user(user_op, &kern_op, sizeof(xen_sysctl_t))) ret = -EFAULT; diff --git a/xen/arch/ia64/linux-xen/Makefile b/xen/arch/ia64/linux-xen/Makefile index 29a6ff5efc..b7f8257579 100644 --- a/xen/arch/ia64/linux-xen/Makefile +++ b/xen/arch/ia64/linux-xen/Makefile @@ -16,3 +16,5 @@ obj-y += tlb.o obj-y += unaligned.o obj-y += unwind.o obj-y += iosapic.o +obj-y += numa.o +obj-y += mm_numa.o diff --git a/xen/arch/ia64/linux-xen/README.origin b/xen/arch/ia64/linux-xen/README.origin index e0a13fe7cf..9a489bca74 100644 --- a/xen/arch/ia64/linux-xen/README.origin +++ b/xen/arch/ia64/linux-xen/README.origin @@ -15,6 +15,8 @@ mca.c -> linux/arch/ia64/kernel/mca.c mca_asm.S -> linux/arch/ia64/kernel/mca_asm.S minstate.h -> linux/arch/ia64/kernel/minstate.h mm_contig.c -> linux/arch/ia64/mm/contig.c +mm_numa.c -> linux/arch/ia64/mm/numa.c +numa.c -> linux/arch/ia64/kernel/numa.c pal.S -> linux/arch/ia64/kernel/pal.S process-linux-xen.c -> linux/arch/ia64/kernel/process.c sal.c -> linux/arch/ia64/kernel/sal.c diff --git a/xen/arch/ia64/linux-xen/mm_contig.c b/xen/arch/ia64/linux-xen/mm_contig.c index 3a0ca725bf..b3a0983648 100644 --- a/xen/arch/ia64/linux-xen/mm_contig.c +++ b/xen/arch/ia64/linux-xen/mm_contig.c @@ -308,4 +308,4 @@ paging_init (void) #endif /* !CONFIG_VIRTUAL_MEM_MAP */ zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page)); } -#endif +#endif /* XEN */ diff --git a/xen/arch/ia64/linux-xen/mm_numa.c b/xen/arch/ia64/linux-xen/mm_numa.c new file mode 100644 index 0000000000..c1b919bf40 --- /dev/null +++ b/xen/arch/ia64/linux-xen/mm_numa.c @@ -0,0 +1,75 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * This file contains NUMA specific variables and functions which can + * be split away from DISCONTIGMEM and are used on NUMA machines with + * contiguous memory. + * + * 2002/08/07 Erich Focht + */ + +#include +#include +#include +#include +#ifndef XEN +#include +#endif +#include +#include +#include +#include + + +/* + * The following structures are usually initialized by ACPI or + * similar mechanisms and describe the NUMA characteristics of the machine. + */ +int num_node_memblks; +struct node_memblk_s node_memblk[NR_NODE_MEMBLKS]; +struct node_cpuid_s node_cpuid[NR_CPUS]; +/* + * This is a matrix with "distances" between nodes, they should be + * proportional to the memory access latency ratios. + */ +u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES]; + +/* Identify which cnode a physical address resides on */ +int +paddr_to_nid(unsigned long paddr) +{ + int i; + + for (i = 0; i < num_node_memblks; i++) + if (paddr >= node_memblk[i].start_paddr && + paddr < node_memblk[i].start_paddr + node_memblk[i].size) + break; + + return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0); +} + +#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA) +/* + * Because of holes evaluate on section limits. + * If the section of memory exists, then return the node where the section + * resides. Otherwise return node 0 as the default. This is used by + * SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where + * the section resides. + */ +int early_pfn_to_nid(unsigned long pfn) +{ + int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec; + + for (i = 0; i < num_node_memblks; i++) { + ssec = node_memblk[i].start_paddr >> PA_SECTION_SHIFT; + esec = (node_memblk[i].start_paddr + node_memblk[i].size + + ((1L << PA_SECTION_SHIFT) - 1)) >> PA_SECTION_SHIFT; + if (section >= ssec && section < esec) + return node_memblk[i].nid; + } + + return 0; +} +#endif diff --git a/xen/arch/ia64/linux-xen/numa.c b/xen/arch/ia64/linux-xen/numa.c new file mode 100644 index 0000000000..35d6fd48bf --- /dev/null +++ b/xen/arch/ia64/linux-xen/numa.c @@ -0,0 +1,67 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ia64 kernel NUMA specific stuff + * + * Copyright (C) 2002 Erich Focht + * Copyright (C) 2004 Silicon Graphics, Inc. + * Jesse Barnes + */ +#ifdef XEN +#include +#endif +#include +#include +#include +#include +#include +#ifdef XEN +#include +#endif + +#ifdef XEN +nodemask_t node_online_map = { { [0] = 1UL } }; +#endif + +u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned; +EXPORT_SYMBOL(cpu_to_node_map); + +cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; + +/** + * build_cpu_to_node_map - setup cpu to node and node to cpumask arrays + * + * Build cpu to node mapping and initialize the per node cpu masks using + * info from the node_cpuid array handed to us by ACPI. + */ +void __init build_cpu_to_node_map(void) +{ + int cpu, i, node; + + for(node=0; node < MAX_NUMNODES; node++) + cpus_clear(node_to_cpu_mask[node]); + + for(cpu = 0; cpu < NR_CPUS; ++cpu) { + node = -1; + for (i = 0; i < NR_CPUS; ++i) + if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) { + node = node_cpuid[i].nid; + break; + } + cpu_to_node_map[cpu] = (node >= 0) ? node : 0; + if (node >= 0) + cpu_set(cpu, node_to_cpu_mask[node]); + } +} diff --git a/xen/arch/ia64/xen/acpi.c b/xen/arch/ia64/xen/acpi.c index af1748f1cb..516a6741c0 100644 --- a/xen/arch/ia64/xen/acpi.c +++ b/xen/arch/ia64/xen/acpi.c @@ -53,6 +53,7 @@ #include #ifdef XEN #include +#include #endif #define BAD_MADT_ENTRY(entry, end) ( \ @@ -457,6 +458,7 @@ acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma) num_node_memblks++; } +static unsigned int numnodes; void __init acpi_numa_arch_fixup (void) { diff --git a/xen/arch/ia64/xen/dom0_ops.c b/xen/arch/ia64/xen/dom0_ops.c index 01aa1e3f0e..d9ca611dbc 100644 --- a/xen/arch/ia64/xen/dom0_ops.c +++ b/xen/arch/ia64/xen/dom0_ops.c @@ -22,8 +22,10 @@ #include #include #include +#include void build_physmap_table(struct domain *d); +#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) extern unsigned long total_pages; @@ -179,17 +181,26 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) return ret; } +/* + * Temporarily disable the NUMA PHYSINFO code until the rest of the + * changes are upstream. + */ +#undef IA64_NUMA_PHYSINFO + long arch_do_sysctl(xen_sysctl_t *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) { long ret = 0; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - switch ( op->cmd ) { case XEN_SYSCTL_physinfo: { +#ifdef IA64_NUMA_PHYSINFO + int i; + node_data_t *chunks; + u64 *map, cpu_to_node_map[MAX_NUMNODES]; +#endif + xen_sysctl_physinfo_t *pi = &op->u.physinfo; pi->threads_per_core = @@ -198,13 +209,70 @@ long arch_do_sysctl(xen_sysctl_t *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) cpus_weight(cpu_core_map[0]) / pi->threads_per_core; pi->sockets_per_node = num_online_cpus() / cpus_weight(cpu_core_map[0]); - pi->nr_nodes = 1; +#ifndef IA64_NUMA_PHYSINFO + pi->nr_nodes = 1; +#endif pi->total_pages = total_pages; pi->free_pages = avail_domheap_pages(); pi->cpu_khz = local_cpu_data->proc_freq / 1000; memset(pi->hw_cap, 0, sizeof(pi->hw_cap)); //memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4); ret = 0; + +#ifdef IA64_NUMA_PHYSINFO + /* fetch memory_chunk pointer from guest */ + get_xen_guest_handle(chunks, pi->memory_chunks); + + printk("chunks=%p, num_node_memblks=%u\n", chunks, num_node_memblks); + /* if it is set, fill out memory chunk array */ + if (chunks != NULL) { + if (num_node_memblks == 0) { + /* Non-NUMA machine. Put pseudo-values. */ + node_data_t data; + data.node_start_pfn = 0; + data.node_spanned_pages = total_pages; + data.node_id = 0; + /* copy memory chunk structs to guest */ + if (copy_to_guest_offset(pi->memory_chunks, 0, &data, 1)) { + ret = -EFAULT; + break; + } + } else { + for (i = 0; i < num_node_memblks && i < PUBLIC_MAXCHUNKS; i++) { + node_data_t data; + data.node_start_pfn = node_memblk[i].start_paddr >> + PAGE_SHIFT; + data.node_spanned_pages = node_memblk[i].size >> PAGE_SHIFT; + data.node_id = node_memblk[i].nid; + /* copy memory chunk structs to guest */ + if (copy_to_guest_offset(pi->memory_chunks, i, &data, 1)) { + ret = -EFAULT; + break; + } + } + } + } + /* set number of notes */ + pi->nr_nodes = num_online_nodes(); + + /* fetch cpu_to_node pointer from guest */ + get_xen_guest_handle(map, pi->cpu_to_node); + + /* if set, fill out cpu_to_node array */ + if (map != NULL) { + /* copy cpu to node mapping to domU */ + memset(cpu_to_node_map, 0, sizeof(cpu_to_node_map)); + for (i = 0; i < num_online_cpus(); i++) { + cpu_to_node_map[i] = cpu_to_node(i); + if (copy_to_guest_offset(pi->cpu_to_node, i, + &(cpu_to_node_map[i]), 1)) { + ret = -EFAULT; + break; + } + } + } +#endif + if ( copy_to_guest(u_sysctl, op, 1) ) ret = -EFAULT; } diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 3f0a67ef2b..9cb2aeaea3 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -26,6 +26,12 @@ #ifdef CONFIG_XEN_SMP #define CONFIG_SMP 1 #define NR_CPUS 64 +#define CONFIG_NUMA +#define CONFIG_ACPI_NUMA +#define NODES_SHIFT 3 +#define MAX_NUMNODES (1 << NODES_SHIFT) +#define NR_NODE_MEMBLKS (MAX_NUMNODES*2) +#define MAX_PXM_DOMAINS 256 #else #undef CONFIG_SMP #define NR_CPUS 1 diff --git a/xen/include/asm-ia64/linux-null/asm/mmzone.h b/xen/include/asm-ia64/linux-null/asm/mmzone.h new file mode 100644 index 0000000000..81447b2f74 --- /dev/null +++ b/xen/include/asm-ia64/linux-null/asm/mmzone.h @@ -0,0 +1 @@ +/* Empty file. */ diff --git a/xen/include/asm-ia64/linux-xen/asm/README.origin b/xen/include/asm-ia64/linux-xen/asm/README.origin index 290ad56a28..9abac91971 100644 --- a/xen/include/asm-ia64/linux-xen/asm/README.origin +++ b/xen/include/asm-ia64/linux-xen/asm/README.origin @@ -5,6 +5,7 @@ # (e.g. with #ifdef XEN or XEN in a comment) so that they can be # easily updated to future versions of the corresponding Linux files. +acpi.h -> linux/include/asm-ia64/acpi.h asmmacro.h -> linux/include/asm-ia64/asmmacro.h cache.h -> linux/include/asm-ia64/cache.h gcc_intrin.h -> linux/include/asm-ia64/gcc_intrin.h @@ -13,6 +14,7 @@ io.h -> linux/include/asm-ia64/io.h kregs.h -> linux/include/asm-ia64/kregs.h mca_asm.h -> linux/include/asm-ia64/mca_asm.h meminit.h -> linux/include/asm-ia64/meminit.h +numa.h -> linux/include/asm-ia64/numa.h page.h -> linux/include/asm-ia64/page.h pal.h -> linux/include/asm-ia64/pal.h pgalloc.h -> linux/include/asm-ia64/pgalloc.h diff --git a/xen/include/asm-ia64/linux/asm/acpi.h b/xen/include/asm-ia64/linux-xen/asm/acpi.h similarity index 99% rename from xen/include/asm-ia64/linux/asm/acpi.h rename to xen/include/asm-ia64/linux-xen/asm/acpi.h index 4c06d45513..bfff8bc804 100644 --- a/xen/include/asm-ia64/linux/asm/acpi.h +++ b/xen/include/asm-ia64/linux-xen/asm/acpi.h @@ -108,8 +108,10 @@ extern void set_cpei_target_cpu(unsigned int cpu); extern unsigned int get_cpei_target_cpu(void); #ifdef CONFIG_ACPI_NUMA +#ifndef XEN /* Proximity bitmap length; _PXM is at most 255 (8 bit)*/ #define MAX_PXM_DOMAINS (256) +#endif extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS]; extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; #endif diff --git a/xen/include/asm-ia64/linux/asm/numa.h b/xen/include/asm-ia64/linux-xen/asm/numa.h similarity index 93% rename from xen/include/asm-ia64/linux/asm/numa.h rename to xen/include/asm-ia64/linux-xen/asm/numa.h index 3ae128fe08..77b444c72c 100644 --- a/xen/include/asm-ia64/linux/asm/numa.h +++ b/xen/include/asm-ia64/linux-xen/asm/numa.h @@ -18,7 +18,9 @@ #include #include #include +#ifndef XEN /* dependency loop when this is included */ #include +#endif #include #include @@ -71,4 +73,8 @@ extern int paddr_to_nid(unsigned long paddr); #endif /* CONFIG_NUMA */ +#ifdef XEN +#define phys_to_nid(paddr) paddr_to_nid(paddr) +#endif + #endif /* _ASM_IA64_NUMA_H */ diff --git a/xen/include/asm-ia64/linux/asm/README.origin b/xen/include/asm-ia64/linux/asm/README.origin index c92c24b828..d9597c0cda 100644 --- a/xen/include/asm-ia64/linux/asm/README.origin +++ b/xen/include/asm-ia64/linux/asm/README.origin @@ -4,7 +4,6 @@ # needs to be changed, move it to ../linux-xen and follow # the instructions in the README there. -acpi.h -> linux/include/asm-ia64/acpi.h atomic.h -> linux/include/asm-ia64/atomic.h bitops.h -> linux/include/asm-ia64/bitops.h break.h -> linux/include/asm-ia64/break.h @@ -26,7 +25,7 @@ linkage.h -> linux/include/asm-ia64/linkage.h machvec.h -> linux/include/asm-ia64/machvec.h machvec_hpsim.h -> linux/include/asm-ia64/machvec_hpsim.h mca.h -> linux/include/asm-ia64/mca.h -numa.h -> linux/include/asm-ia64/numa.h +nodedata.h -> linux/include/asm-ia64/nodedate.h numnodes.h -> linux/include/asm-ia64/numnodes.h param.h -> linux/include/asm-ia64/param.h patch.h -> linux/include/asm-ia64/patch.h diff --git a/xen/include/asm-ia64/linux/asm/nodedata.h b/xen/include/asm-ia64/linux/asm/nodedata.h new file mode 100644 index 0000000000..9978c7ce75 --- /dev/null +++ b/xen/include/asm-ia64/linux/asm/nodedata.h @@ -0,0 +1,52 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2000 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2002 NEC Corp. + * Copyright (c) 2002 Erich Focht + * Copyright (c) 2002 Kimio Suganuma + */ +#ifndef _ASM_IA64_NODEDATA_H +#define _ASM_IA64_NODEDATA_H + +#include +#include + +#include +#include + +#ifdef CONFIG_NUMA + +/* + * Node Data. One of these structures is located on each node of a NUMA system. + */ + +struct pglist_data; +struct ia64_node_data { + short active_cpu_count; + short node; + struct pglist_data *pg_data_ptrs[MAX_NUMNODES]; +}; + + +/* + * Return a pointer to the node_data structure for the executing cpu. + */ +#define local_node_data (local_cpu_data->node_data) + +/* + * Given a node id, return a pointer to the pg_data_t for the node. + * + * NODE_DATA - should be used in all code not related to system + * initialization. It uses pernode data structures to minimize + * offnode memory references. However, these structure are not + * present during boot. This macro can be used once cpu_init + * completes. + */ +#define NODE_DATA(nid) (local_node_data->pg_data_ptrs[nid]) + +#endif /* CONFIG_NUMA */ + +#endif /* _ASM_IA64_NODEDATA_H */ diff --git a/xen/include/asm-ia64/xenpage.h b/xen/include/asm-ia64/xenpage.h index f5b0f74e70..a9dc9b4a68 100644 --- a/xen/include/asm-ia64/xenpage.h +++ b/xen/include/asm-ia64/xenpage.h @@ -1,10 +1,6 @@ #ifndef _ASM_IA64_XENPAGE_H #define _ASM_IA64_XENPAGE_H -#ifdef CONFIG_DISCONTIGMEM -#error "xenpage.h: page macros need to be defined for CONFIG_DISCONTIGMEM" -#endif - #undef mfn_valid #undef page_to_mfn #undef mfn_to_page diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index d7b35b4524..78f0d57dbf 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -28,6 +28,7 @@ __DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); __DEFINE_XEN_GUEST_HANDLE(uint, unsigned int); __DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long); +__DEFINE_XEN_GUEST_HANDLE(u64, unsigned long); DEFINE_XEN_GUEST_HANDLE(char); DEFINE_XEN_GUEST_HANDLE(int); DEFINE_XEN_GUEST_HANDLE(long); -- 2.30.2